package main

import "fmt"

/**
	切片Slice
	1、slice 是对底层数组的一个试图,操作slice中的数据会对愿数组的数据产生影响
	2、在一个方法中修改传递进来的数组不会对外部数组产生影响，除非传递过来的是数组指针
       如果方法中传递的是数组的slice,那么修改slice中的数据，会对原数组产生影响
	3、可以对一个slice再次进行slice操作，则新slice是在原slice的数据上进行操作
	4、一个示例：
		arr      		数据	0  1  2  3  4  5  6  7
		s1:=arr[2:6]    数据       2  3  4  5
        s1              下标		  0  1  2  3  4  5  （从slice中，s1[4],s1[5]数据访问不到，但是它是真实存在的）
		s1              len	(4)  下标取值，只可以取到 < len 的值
		s1				cap (6)  指的是容量，>len的数据不可见，但真实存在
		s2:=s1[3:5]     数据                5  6  （可以获取到6）
		...
	5、slice 可以向后扩展，不可向前扩展
	6、s[i]不可超越len(arr),向后扩展不可以超越底层数组cap(arr)
	7、向slice中添加元素时，添加元素如果超越cap,系统会重新分配一个更大的底层数组
	8、由于值传递的关系，必须接收append操作的返回值
	9、创建一个slice
		> var s int[]            // 创建一个slice,此时这个slice就可以使用了
		> var arr = []int{1,3,4} // 创建一个带有初始值的slice
		> var s = make([]int,16) // 创建一个长度和容量为16的slice
		> var s = make([]int,16,32) // 创建一个长度为16容量为32的slice
	10、复制slice,使用函数 copy
	11、删除slice中的元素
			> 系统中没有提供默认的方法，需要自己使用 append 方法来计算，可以看看 append 方法的第二个参数是怎么拼接的
*/

/**
更新slice中的值，会对愿数组中的值产生影响
*/
func updateSlice(arr []int) {
	arr[0] = 100
}

/**
创建slice
*/
func createSlice() {
	var s1 []int
	fmt.Println("s1", s1)

	for i := 0; i < 50; i++ {
		fmt.Printf("len=(%d),cap=(%d)\n", len(s1), cap(s1))
		s1 = append(s1, i*2)
	}
	fmt.Println("s1", s1)

	var s2 = []int{1, 3, 4, 5}
	fmt.Println("s2", s2)

	var s3 = make([]int, 10)
	fmt.Println("s3", s3)

	var s4 = make([]int, 10, 20)
	fmt.Println("s4", s4)
}

/**
复制slice
*/
func copySlice() {
	var s1 = []int{1, 3, 5}
	var s2 = make([]int, 10, 20)
	copy(s2, s1)
	fmt.Println(s1)
	fmt.Println(s2)
}

/**
删除slice中的元素
*/
func deleteSliceElement() {
	var s1 = []int{1, 3, 5, 6, 7}
	fmt.Println("删除元素 5 ")

	var s2 = append(s1[:2], s1[3:]...)
	fmt.Println(s2)

}

func main() {

	// 定义一个数组
	arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	// 角标从0开始，>= 开始索引，< 结束索引
	s := arr[2:6]

	fmt.Println("arr[2:6]==> ", s)
	fmt.Println("arr[:6]==> ", arr[:6])
	s1 := arr[2:]
	fmt.Println("s1==> ", s1)
	s2 := arr[:]
	fmt.Println("s2==> ", s2)

	fmt.Println("After updateSlice(s1)")
	updateSlice(s1)
	fmt.Println("s1===>", s1)
	fmt.Println("arr", arr)

	fmt.Println("After updateSlice(s2)")
	updateSlice(s2)
	fmt.Println("s2===>", s2)
	fmt.Println("arr", arr)

	fmt.Println("ReSlice")
	s2 = s2[:5]
	fmt.Println("s2===>", s2)
	s2 = s2[2:]
	fmt.Println("s2===>", s2)

	fmt.Println("扩展 Slice")
	arr[0], arr[2] = 0, 2
	s1 = arr[2:6] // s1 只有4个元素
	s2 = s1[3:5]  // s2 会报错，还是可以获取到元素？
	fmt.Println("s1===>", s1)
	fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d\n", s1, len(s1), cap(s1))
	fmt.Println("s2===>", s2)
	fmt.Printf("s1=%v,len(s2)=%d,cap(s2)=%d\n", s1, len(s2), cap(s2))

	fmt.Println("向slice中增加元素")
	// 因为s2对应的原数组后面还有值，此时append一个值会覆盖原数组中的值
	s3 := append(s2, 10)
	// s4和s5不在是对arr的一个映射
	s4 := append(s3, 11)
	s5 := append(s4, 12)
	fmt.Println("s3,s4,s5", s3, s4, s5)
	fmt.Println("arr===>", arr)

	fmt.Println("创建 slice")
	createSlice()

	fmt.Println("复制slice")
	copySlice()

	fmt.Println("删除slice中的原色")
	deleteSliceElement()
}
